﻿using BCCommon;
using BCCommon.Enums;
using BCCommon.NPinyin;
using BCData.Sim.Admin.Admin;
using BCData.Sim.Admin.StaffOrganizationMappingRecord;
using BCData.Sim.Company.Company;
using BCData.Sim.Company.CompanyBusinessType;
using BCData.Sim.Company.JobTitle;
using BCData.Sim.Company.Position;
using BCDto.Sim.Admin.Admin;
using BCDto.Sim.Company.Company;
using BCDto.Sim.Company.Department;
using BCEntity.Common.EntityNameConst;
using BCEntity.Sim.Admin.StaffOrganizationMappingRecord;
using BCEntity.Sim.Company.Company;
using BCEntity.Sim.Company.Position;
using BCService.Sim.Company.Department;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BCService.Sim.Company.Company
{
    public class CompanyService : ICompanyService
    {
        private readonly IDatabaseContext databaseContext;
        private readonly ICompanyBusinessTypeData companyBusinessTypeData;
        private readonly ICompanyData companyData;
        private readonly IDepartmentService departmentService;
        private readonly IAdminData adminData;
        private readonly IPositionData positionData;
        private readonly IJobTitleData jobTitleData;
        private readonly IStaffOrganizationMappingRecordData staffOrganizationMappingRecordData;
        private readonly IRedisService redisService;

        public CompanyService(IDatabaseContext databaseContext,
            ICompanyBusinessTypeData companyBusinessTypeData,
            ICompanyData companyData,
            IDepartmentService departmentService,
            IAdminData adminData,
            IStaffOrganizationMappingRecordData staffOrganizationMappingRecordData,
            IPositionData positionData,
            IJobTitleData jobTitleData,
            IRedisService redisService)
        {
            this.databaseContext = databaseContext;
            this.companyBusinessTypeData = companyBusinessTypeData;
            this.companyData = companyData;
            this.departmentService = departmentService;
            this.adminData = adminData;
            this.staffOrganizationMappingRecordData = staffOrganizationMappingRecordData;
            this.positionData = positionData;
            this.jobTitleData = jobTitleData;
            this.redisService = redisService;
        }
        #region 添加公司
        public CompanyDto Add(AdminDto adminDto, CompanyRequestDto companyRequestDto)
        {
            if (!this.adminData.CheckAdminExists(companyRequestDto.CompanyAdminId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("负责人不是公司员工，请确认负责人信息正确");
            }

            var staffDto = this.adminData.GetAdmin(companyRequestDto.CompanyAdminId).GetAwaiter().GetResult();
            CompanyEntity entity = companyRequestDto.As<CompanyEntity>();
            entity.CompanySubName = Pinyin.GetInitials(entity.CompanyName);
            entity.AdminFullName = staffDto.FullName;
            entity.EditerId = adminDto.AdminId;
            entity.Editer = adminDto.FullName;
            entity.BusinessTypeName = this.companyBusinessTypeData.GetEntity(entity.BusinessType).GetAwaiter().GetResult().BusinessTypeName;
            if (this.companyData.CheckCompanySubNameExists(entity.CompanySubName, null).GetAwaiter().GetResult())
            {
                string companySubName = entity.CompanySubName + new Random().Next(0, 10);
                while (this.companyData.CheckCompanySubNameExists(entity.CompanySubName, null).GetAwaiter().GetResult())
                {
                    companySubName = entity.CompanySubName + new Random().Next(0, 10);
                };
                entity.CompanySubName = companySubName;
            }
            databaseContext.BeginTransaction();
            var result = this.companyData.Add(entity).GetAwaiter().GetResult();
            if (result == null)
            {
                throw new ArgumentException("创建公司信息失败");
            }

            var staffOrganizationMappingRecords = this.staffOrganizationMappingRecordData.GetList(entity.CompanyAdminId).GetAwaiter().GetResult();

            var departmentRequestDto = new DepartmentRequestDto
            {
                DepartmentCreateTime = DateTime.Now,
                DepartmentName = "总经办",
                CompanyId = result.CompanyId
            };
            var departmentResult = this.departmentService.Add(adminDto,departmentRequestDto);
            if (departmentResult == null)
            {
                throw new ArgumentException("创建公司总经办部门时失败，请重试");
            }

            PositionEntity position = new PositionEntity
            {
                CompanyId = result.CompanyId,
                DepartmentId = departmentResult.DepartmentId,
                PositionName = "总经理",
                PositionNo = "SUB" + result.CompanyId + "-000001",
                CreateAdminId = adminDto.AdminId,
                CreateAdminName = adminDto.FullName
            };
            var positionResult = this.positionData.Add(position).GetAwaiter().GetResult();
            if (positionResult == null)
            {
                throw new ArgumentException("创建公司部门岗位时失败，请重试");
            }
            var jobTitleResult = this.jobTitleData.GetEntity("StaffTitle_President").GetAwaiter().GetResult();

            var staffOrganizationMappingRecordEntity = new StaffOrganizationMappingRecordEntity
            {
                AdminId = staffDto.AdminId,
                FullName = staffDto.FullName,
                CompanyId = result.CompanyId,
                CompanyName = result.CompanyName,
                DepartmentId = departmentResult.DepartmentId,
                DepartmentName = departmentResult.DepartmentName,
                IsActive = false,
                JobDuty = positionResult.PositionName,
                JobTitle = jobTitleResult.JobTitle,
                JobDutyKey = positionResult.PositionNo,
                JobTitleKey = jobTitleResult.JobTitleNo
            };

            var staffOrganizationMappingResult = this.staffOrganizationMappingRecordData.Add(staffOrganizationMappingRecordEntity).GetAwaiter().GetResult();
            if (staffOrganizationMappingResult == null)
            {
                throw new ArgumentException("创建公司时失败，请重试");
            }
            if (!staffOrganizationMappingRecords.Any())
            {
                bool status = false;
                while (!status)
                {
                    status = this.adminData.UpdateDepartmentInfo(entity.CompanyAdminId, result.CompanyId, result.CompanyName, departmentResult.DepartmentId, departmentResult.DepartmentName).GetAwaiter().GetResult();
                }
            }
            databaseContext.Commit();
            return result.As<CompanyDto>();
        }
        #endregion

        #region 修改公司
        public CompanyDto Update(AdminDto adminDto, CompanyPutDto companyPutDto)
        {
            if (!this.adminData.CheckAdminExists(companyPutDto.CompanyAdminId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("负责人不是公司员工，请确认负责人信息正确");
            }

            CompanyEntity entity = companyPutDto.As<CompanyEntity>();
            entity.CompanySubName = Pinyin.GetInitials(entity.CompanyName);
            entity.AdminFullName = this.adminData.GetAdmin(entity.CompanyAdminId).GetAwaiter().GetResult().FullName;
            entity.EditerId = adminDto.AdminId;
            entity.Editer = adminDto.FullName;
            entity.BusinessTypeName = this.companyBusinessTypeData.GetEntity(entity.BusinessType).GetAwaiter().GetResult().BusinessTypeName;
            var companyEntity = this.Get(companyPutDto.CompanyId);
            if (companyEntity.CompanySubName != entity.CompanySubName)
            {
                if (this.companyData.CheckCompanySubNameExists(entity.CompanySubName, entity.CompanyId).GetAwaiter().GetResult())
                {
                    string companySubName = entity.CompanySubName + new Random().Next(0, 10);
                    while (this.companyData.CheckCompanySubNameExists(entity.CompanySubName, entity.CompanyId).GetAwaiter().GetResult())
                    {
                        companySubName = entity.CompanySubName + new Random().Next(0, 10);
                    };
                    entity.CompanySubName = companySubName;
                }
            }

            databaseContext.BeginTransaction();

            var result = this.companyData.Update(entity).GetAwaiter().GetResult();
            if (result != null)
            {
                if (companyEntity.CompanyAdminId != companyPutDto.CompanyAdminId)
                {
                    var adminEntity = this.adminData.GetAdmin(companyEntity.CompanyAdminId).GetAwaiter().GetResult();
                    var staffMappingList = this.staffOrganizationMappingRecordData.GetList(companyEntity.CompanyAdminId).GetAwaiter().GetResult();
                    var staffMappingEntity = staffMappingList.SingleOrDefault(p => p.CompanyId == adminEntity.CompanyId && p.DepartmentName == "总经办");
                    int departmentId = 0;
                    if (staffMappingEntity != null)
                    {
                        long staffMappingId = staffMappingEntity.StaffOrganizationMappingRecordId;
                        departmentId = staffMappingEntity.DepartmentId;
                        this.staffOrganizationMappingRecordData.Delete(staffMappingId).GetAwaiter().GetResult();
                    }

                    var departmentDtos = departmentService.GetList(companyEntity.CompanyId);
                    if (!departmentDtos.Any(p => p.DepartmentName == "总经办"))
                    {
                        var departmentRequestDto = new DepartmentRequestDto
                        {
                            DepartmentCreateTime = DateTime.Now,
                            DepartmentName = "总经办",
                            CompanyId = result.CompanyId
                        };
                        var departmentResult = this.departmentService.Add(adminDto, departmentRequestDto);
                        if (departmentResult == null)
                        {
                            throw new ArgumentException("创建公司总经办部门时失败，请重试");
                        }
                    }
                    else
                    {
                        departmentId = departmentDtos.Single(p => p.DepartmentName == "总经办").DepartmentId;
                    }

                    var positionResult = this.positionData.GetEntity(result.CompanyId,departmentId, adminEntity.JobDutyKey).GetAwaiter().GetResult();
                    var jobTitleResult = this.jobTitleData.GetEntity("StaffTitle_President").GetAwaiter().GetResult();
                    var staffOrganizationMappingRecordEntity = new StaffOrganizationMappingRecordEntity
                    {
                        AdminId = entity.CompanyAdminId,
                        FullName = entity.AdminFullName,
                        CompanyId = result.CompanyId,
                        CompanyName = result.CompanyName,
                        DepartmentId = departmentId,
                        DepartmentName = "总经办",
                        IsActive = false,
                        JobDuty = positionResult.PositionName,
                        JobTitle = jobTitleResult.JobTitle,
                        JobDutyKey = positionResult.PositionNo,
                        JobTitleKey = jobTitleResult.JobTitleNo
                    };
                    var staffOrganizationMappingResult = this.staffOrganizationMappingRecordData.Add(staffOrganizationMappingRecordEntity).GetAwaiter().GetResult();
                    if (staffOrganizationMappingResult == null)
                    {
                        throw new ArgumentException("更换公司负责人时失败，请重试");
                    }
                }
            }
            databaseContext.Commit();
            return result.As<CompanyDto>();
        }
        #endregion

        #region 删除公司

        public void Delete(int companyId)
        {
            var companyEntity = this.companyData.GetEntity(companyId).GetAwaiter().GetResult();
            if (companyEntity.InUse.HasValue && companyEntity.InUse.Value)
            {
                throw new ArgumentException("此公司存在部门及员工，无法删除!");
            }

            if (!this.companyData.Delete(companyId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("删除公司时失败，请重试!");
            }
        }
        #endregion

        public CompanyDto Get(int companyId)
        {
            string key = string.Format("{0}:CompanyId={1}", EntityNameConst.CompanyEntity, companyId);
            var result = this.redisService.TryGet(key, () =>
            {
                var data = this.companyData.GetEntity(companyId).GetAwaiter().GetResult();
                return data;
            }, TimeSpan.FromMinutes(30));

            return result.As<CompanyDto>();
        }

        public IEnumerable<CompanyDto> GetList(AdminDto adminDto)
        {
            if (adminDto.IsSystemAccount)
            {
                return this.companyData.GetList().GetAwaiter().GetResult().As<IEnumerable<CompanyDto>>();
            }
            else
            {
                return new List<CompanyDto>() { this.companyData.GetEntity(adminDto.CompanyId).GetAwaiter().GetResult().As<CompanyDto>() };
            }
        }

        public PageableList<CompanyDto> Query(string companyBusinessTypeCode, string companyName, CompanyStatus? companyStatus, DateTime? start, DateTime? end, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            var list = this.companyData.Query(companyBusinessTypeCode, companyName, companyStatus, start, end, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();
            return new PageableList<CompanyDto>()
            {
                Items = list.Item1.As<IEnumerable<CompanyDto>>(),
                Count = list.Item2
            };
        }

        public void UpdateCompanyAdminId(long companyId, long adminId)
        {
            this.companyData.UpdateCompanyAdminId(companyId, adminId).GetAwaiter().GetResult();
        }

        public void JobAdd(long companyAdminId)
        {
            var staffDto = this.adminData.GetAdmin(companyAdminId).GetAwaiter().GetResult().As<AdminDto>();
            
            databaseContext.BeginTransaction();
            var staffOrganizationMappingRecords = this.staffOrganizationMappingRecordData.GetList(companyAdminId).GetAwaiter().GetResult();

            var departmentRequestDto = new DepartmentRequestDto
            {
                DepartmentCreateTime = DateTime.Now,
                DepartmentName = "总经办",
                CompanyId = staffDto.CompanyId
            };
            var departmentResult = this.departmentService.Add(staffDto, departmentRequestDto);
            if (departmentResult == null)
            {
                throw new ArgumentException("创建公司总经办部门时失败，请重试");
            }

            PositionEntity position = new PositionEntity
            {
                CompanyId = staffDto.CompanyId,
                DepartmentId = departmentResult.DepartmentId,
                PositionName = "总经理",
                PositionNo = "SUB" + staffDto.CompanyId + "-000001",
                CreateAdminId = staffDto.AdminId,
                CreateAdminName = staffDto.FullName
            };
            var positionResult = this.positionData.Add(position).GetAwaiter().GetResult();
            if (positionResult == null)
            {
                throw new ArgumentException("创建公司部门岗位时失败，请重试");
            }
            var jobTitleResult = this.jobTitleData.GetEntity("StaffTitle_President").GetAwaiter().GetResult();

            var staffOrganizationMappingRecordEntity = new StaffOrganizationMappingRecordEntity
            {
                AdminId = staffDto.AdminId,
                FullName = staffDto.FullName,
                CompanyId = staffDto.CompanyId,
                CompanyName = staffDto.CompanyName,
                DepartmentId = departmentResult.DepartmentId,
                DepartmentName = departmentResult.DepartmentName,
                IsActive = false,
                JobDuty = positionResult.PositionName,
                JobTitle = jobTitleResult.JobTitle,
                JobDutyKey = positionResult.PositionNo,
                JobTitleKey = jobTitleResult.JobTitleNo
            };

            var staffOrganizationMappingResult = this.staffOrganizationMappingRecordData.Add(staffOrganizationMappingRecordEntity).GetAwaiter().GetResult();
            if (staffOrganizationMappingResult == null)
            {
                throw new ArgumentException("创建公司时失败，请重试");
            }
            if (!staffOrganizationMappingRecords.Any())
            {
                bool status = false;
                while (!status)
                {
                    status = this.adminData.UpdateDepartmentInfo(companyAdminId, staffDto.CompanyId, staffDto.CompanyName, departmentResult.DepartmentId, departmentResult.DepartmentName).GetAwaiter().GetResult();
                }
            }
            databaseContext.Commit();
        }
    }
}
